#!/usr/bin/env python
#
# Copyright 2008 Doug Hellmann.
#
"""Tests for the vtr.py module.
"""

__version__ = "$Id$"

# Import system modules
import datetime
import logging
from cStringIO import StringIO
import unittest

# Import local modules
from vtr import *

# Module
DEBUG = False
if DEBUG:
    level = logging.DEBUG
else:
    level = logging.INFO
logging.basicConfig(level=level,
                    format='%(asctime)s %(levelname)-8s %(message)s',
                    )

class ParseDateTest(unittest.TestCase):
    
    def testDate(self):
        response = ParsedDate('02 Oct 1902')
        self.failUnlessEqual(response.date, datetime.date(1902, 10, 2))
        self.failUnlessEqual(response.sic, False)

    def testDateSic(self):
        response = ParsedDate('02 Oct 1902 [sic]')
        self.failUnlessEqual(response.date, datetime.date(1902, 10, 2))
        self.failUnlessEqual(response.sic, True)
        
class ParsedSentenceTest(unittest.TestCase):
    
    def testPaid(self):
        response = ParsedSentence('ss pd')
        self.failUnlessEqual(response.kind, 'S')
        self.failUnlessEqual(response.code, 'P')
        self.failUnlessEqual(response.amount, 0)
        self.failUnlessEqual(response.note, '')
        self.failUnlessEqual(response.date, None)
        self.failUnlessEqual(str(response), 'Served: Paid $0.00')
        return
    
    def testSentenceFine(self):
        response = ParsedSentence('sr 5.00 F')
        self.failUnlessEqual(response.kind, 'R')
        self.failUnlessEqual(response.code, 'F')
        self.failUnlessEqual(response.amount, 5.0)
        self.failUnlessEqual(response.note, '')
        self.failUnlessEqual(response.date, None)
        self.failUnlessEqual(str(response), 'Rendered: Fine $5.00')
        return
        
    def testSentenceFineDate(self):
        response = ParsedSentence('ss 5.00 F 01 Jan 1902')
        self.failUnlessEqual(response.kind, 'S')
        self.failUnlessEqual(response.code, 'F')
        self.failUnlessEqual(response.amount, 5.0)
        self.failUnlessEqual(response.note, '')
        self.failUnlessEqual(response.date.date, datetime.date(1902, 1, 1))
        self.failIf(response.date.sic)
        self.failUnlessEqual(str(response), 'Served: Fine $5.00 01 Jan 1902')
        return

    def testNoAmount(self):
        response = ParsedSentence('ss W 03 Oct 1902 (Turned over to streets)')
        self.failUnlessEqual(response.kind, 'S')
        self.failUnlessEqual(response.code, 'W')
        self.failUnlessEqual(response.amount, 0)
        self.failUnlessEqual(response.note, 'Turned over to streets')
        self.failUnlessEqual(response.date.date, datetime.date(1902, 10, 3))
        self.failIf(response.date.sic)
        self.failUnlessEqual(str(response), 'Served: Work 0 03 Oct 1902 (Turned over to streets)')
        return

    def testNoteInParens(self):
        response = ParsedSentence('ss W (Turned over to streets)')
        self.failUnlessEqual(response.kind, 'S')
        self.failUnlessEqual(response.code, 'W')
        self.failUnlessEqual(response.amount, 0)
        self.failUnlessEqual(response.note, 'Turned over to streets')
        self.failUnlessEqual(response.date, None)
        self.failIf(response.date_sic)
        self.failUnlessEqual(str(response), 'Served: Work 0 (Turned over to streets)')
        return

    def testNoteInParensWithDate(self):
        response = ParsedSentence('ss W 03 Oct 1902 (Turned over to streets)')
        self.failUnlessEqual(response.kind, 'S')
        self.failUnlessEqual(response.code, 'W')
        self.failUnlessEqual(response.amount, 0)
        self.failUnlessEqual(response.note, 'Turned over to streets')
        self.failUnlessEqual(response.date.date, datetime.date(1902, 10, 3))
        self.failIf(response.date.sic)
        self.failUnlessEqual(str(response), 'Served: Work 0 03 Oct 1902 (Turned over to streets)')
        return
        
class ParsedParticipantTest(unittest.TestCase):
    """Tests for parsing participants"""

    def testFullyQualified(self):
        p = ParsedParticipant('d First Middle Last title=Dr. suffix=Jr. alias=AnotherName (This is the note.)')
        self.failUnlessEqual(p.role, 'Defendant')
        self.failUnlessEqual(p.first, 'First')
        self.failUnlessEqual(p.middle, 'Middle')
        self.failUnlessEqual(p.last, 'Last')
        self.failUnlessEqual(p.title, 'Dr.')
        self.failUnlessEqual(p.suffix, 'Jr.')
        self.failUnlessEqual(p.alias, 'AnotherName')
        self.failUnlessEqual(p.note, 'This is the note.')
        return

    def testNameOnly(self):
        p = ParsedParticipant('d First Middle Last')
        self.failUnlessEqual(p.role, 'Defendant')
        self.failUnlessEqual(p.first, 'First')
        self.failUnlessEqual(p.middle, 'Middle')
        self.failUnlessEqual(p.last, 'Last')
        self.failUnlessEqual(p.title, '')
        self.failUnlessEqual(p.suffix, '')
        self.failUnlessEqual(p.alias, '')
        self.failUnlessEqual(p.note, '')
        return

    def testInitialAndName(self):
        p = ParsedParticipant('d F. Last')
        self.failUnlessEqual(p.role, 'Defendant')
        self.failUnlessEqual(p.first, 'F.')
        self.failUnlessEqual(p.middle, '')
        self.failUnlessEqual(p.last, 'Last')
        self.failUnlessEqual(p.title, '')
        self.failUnlessEqual(p.suffix, '')
        self.failUnlessEqual(p.alias, '')
        self.failUnlessEqual(p.note, '')
        return

    def testInitialsAndName(self):
        p = ParsedParticipant('d F. M. Last')
        self.failUnlessEqual(p.role, 'Defendant')
        self.failUnlessEqual(p.first, 'F.')
        self.failUnlessEqual(p.middle, 'M.')
        self.failUnlessEqual(p.last, 'Last')
        self.failUnlessEqual(p.title, '')
        self.failUnlessEqual(p.suffix, '')
        self.failUnlessEqual(p.alias, '')
        self.failUnlessEqual(p.note, '')
        return
    
    def testRoles(self):
        codes = [ ('ao','Arresting Officer'),
                  ('d','Defendant'),
                  ('w','Witness'),
                  ('wd','Witness, Defense'),
                  ('dw','Witness, Defense'),
                  ]
        for code, expected in codes:
            p = ParsedParticipant('%s First Middle Last' % code)
            self.failUnlessEqual(p.role, expected)
        return

class VaugeTextRecordTest(unittest.TestCase):

    def testInit(self):
        r = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        ao W. E. Jackson
        l Clayton Street
        v 360
        w W. E. Jackson
        p guilty
        sr 5.00 F
        ss 5.00
        """.split('\n'))
        self.failUnlessEqual(r.book, '1902/6')
        self.failUnless(isinstance(r.defendant, ParsedParticipant))
        self.failUnlessEqual(r.defendant.first, 'Fred')
        self.failUnlessEqual(r.defendant.last, 'Davis')
        return

    def testDefendantDetails(self):
        r = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        d Fred Davis
        r b
        g m
        """.split('\n'))
        self.failUnlessEqual(r.book, '1902/6')
        self.failUnless(isinstance(r.defendant, ParsedParticipant))
        self.failUnlessEqual(r.defendant.first, 'Fred')
        self.failUnlessEqual(r.defendant.last, 'Davis')
        self.failUnlessEqual(r.defendant.race, 'B')
        self.failUnlessEqual(r.defendant.gender, 'M')
        return

    def testNotes(self):
        r = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        d Fred Davis
        n Line one.
        n Line two.
        n  Line three.
        """.split('\n'))
        self.failUnlessEqual(r.notes, 'Line one.\nLine two.\nLine three.')
        return

    def testNoDefendant(self):
        try:
            r = VagueTextRecord("""
            b 1902/6
            pg 26
            c 676
            ad 29 Sept 1902
            """.split('\n'))
        except ValueError, err:
            self.failUnlessEqual(str(err), 'No Defendant found for Case 676 in 1902/6')
        else:
            self.fail('Expected ValueError')
        return

    def testSentenceWithoutHearingDate(self):
        try:
            rec = VagueTextRecord("""
            b 1902/6
            pg 26
            c 676
            ad 29 Sept 1902
            d Fred Davis
            sr 5.00 F
            ss 5.00
            """.split('\n'))
        except ValueError, err:
            self.failUnlessEqual(str(err), 'There is no hearing date for Case 676 in 1902/6')
        else:
            self.fail('Expected ValueError')
        return

    def testDefaultSentenceDateToHearing(self):
        rec = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        sr 5.00 F
        ss 5.00
        """.split('\n'))
        for sentence in rec.sentences:
            self.failUnlessEqual(sentence.date.date, datetime.date(1902, 9, 30))
        return

    def testDefaultYearToArrestDate(self):
        rec = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1903
        d Fred Davis
        sr 5.00 F
        ss 5.00
        """.split('\n'))
        self.failUnlessEqual(rec.year, 1902)
        return

    def testDefaultYearToBookDate(self):
        rec = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        hd 30 Sept 1903
        d Fred Davis
        sr 5.00 F
        ss 5.00
        """.split('\n'))
        self.failUnlessEqual(rec.year, 1902)
        return

    def testDoNotOverwiteSentenceDate(self):
        rec = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        sr 5.00 F 01 Oct 1902
        ss W 01 Oct 1902 (Turned over to streets)
        """.split('\n'))
        for sentence in rec.sentences:
            self.failUnlessEqual(sentence.date.date, datetime.date(1902, 10, 1))
        return
        
    def testDefaultPaid(self):
        rec = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        sr 5.00 F 01 Oct 1902
        sc 2.50 F
        ss pd
        """.split('\n'))
        paid = rec.sentences[-1]
        self.failUnlessEqual(paid.amount, 7.5)
        return

    def testDefaultYear(self):
        rec = VagueTextRecord("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        sr 5.00 F 01 Oct 1902
        sc 2.50 F
        ss pd
        """.split('\n'))
        self.failUnlessEqual(rec.year, 1902)
        return


class ParseStreamTest(unittest.TestCase):

    def testEndWithBlankLine(self):
        buffer = StringIO("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        ao W. E. Jackson
        l Clayton Street
        v 360
        w W. E. Jackson
        p guilty
        sr 5.00 F
        ss 5.00

        b 1902/6
        pg 26
        c 677
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Jim McQueen
        ao J. E. Jackson
        l Clayton Street
        v 360
        w W. E. Jackson
        p guilty
        sr 5.00 F
        sr 1.25 C
        ss 6.25
        """)
        recs = list(parse_stream(buffer))
        self.failUnlessEqual(len(recs), 2)
        return
    
    def testEndNoNewline(self):
        buffer = StringIO("""
        b 1902/6
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        ao W. E. Jackson
        l Clayton Street
        v 360
        w W. E. Jackson
        p guilty
        sr 5.00 F
        ss 5.00

        b 1902/6
        pg 26
        c 677
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Jim McQueen
        ao J. E. Jackson
        l Clayton Street
        v 360
        w W. E. Jackson
        p guilty
        sr 5.00 F
        sr 1.25 C
        ss 6.25""")
        recs = list(parse_stream(buffer))
        self.failUnlessEqual(len(recs), 2)
        return
  
    def testDefaultBook(self):
        buffer = StringIO("""
        b 1902/6
       
        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        ao W. E. Jackson
        l Clayton Street
        v 360
        w W. E. Jackson
        p guilty
        sr 5.00 F
        ss 5.00
        """)
        recs = list(parse_stream(buffer))
        self.failUnlessEqual(len(recs), 1)
        self.failUnlessEqual(recs[0].book, '1902/6')
        return

    def testDefaultBookExtraBlankLine(self):
        buffer = StringIO("""
        b 1902/6


        pg 26
        c 676
        ad 29 Sept 1902
        hd 30 Sept 1902
        d Fred Davis
        ao W. E. Jackson
        l Clayton Street
        v 360
        w W. E. Jackson
        p guilty
        sr 5.00 F
        ss 5.00
        """)
        recs = list(parse_stream(buffer))
        self.failUnlessEqual(len(recs), 1)
        self.failUnlessEqual(recs[0].book, '1902/6')
        return

class ParsedViolationTest(unittest.TestCase):

    def testCodeOnly(self):
        v = ParsedViolation('v 363')
        self.failUnlessEqual(v.code, '363')
        self.failUnlessEqual(v.note, '')
        self.failUnlessEqual(str(v), '363')
        return

    def testNoteOnly(self):
        v = ParsedViolation('v (note)')
        self.failUnlessEqual(v.code, 'none')
        self.failUnlessEqual(v.note, 'note')
        self.failUnlessEqual(str(v), 'none (note)')
        return
    
    def testCombination(self):
        v = ParsedViolation('v 363 (note)')
        self.failUnlessEqual(v.code, '363')
        self.failUnlessEqual(v.note, 'note')
        self.failUnlessEqual(str(v), '363 (note)')
        return
        
        return

if __name__ == '__main__':
    unittest.main()
